8. OAuth

  • OAuth官网 1
  • OAuth官网 2
  • 一种授权机制,一种开发网络标准,主要用来颁发token
  • 当前版本3.0
  • 流程图如下: AbstractProtocalFlow
  • OAuth 2.0定义了authorization grant四种授权方式。
    • 授权码模式(authorization code)
    • 简化模式(implicit)
    • 密码模式(resource owner password credentials)
    • 客户端模式(client credential

8.1. Authorization Code

  • 适用于有后端的web应用

  • 授权码通过前端传送

  • 优点是令牌后端存储,且与资源服务器通信都在后端完成,避免令牌泄露

  • 下图是模拟的用户访问北京图灵学院的博客平台后,利用QQ授权服务器, 整个流程发生的信息交换流程图:

    CodePattern

下面对整个流程做一下解释:

  • 北京图灵学院博客服务器第一次向qq授权服务器申请认证的URI,包含以下参数:

    • response_type:表示授权类型,必选项,此处的值固定为”code”

    • client_id:表示客户端的ID,必选项

    • redirect_uri:表示重定向URI,可选项

    • scope:表示申请的权限范围,可选项

    • state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。

    • 例如:

        GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz
                &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
        Host: server.example.com
      
  • qq服务器向北京图灵学院博客服务器的URI,包含以下参数:

    • code:表示授权码,必选项。

      • 该码的有效期应该很短,通常设为10分钟,
      • 客户端只能使用该码一次,否则会被授权服务器拒绝。
      • 该码与客户端ID和重定向URI,是一一对应关系。
    • state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。

    • 例如:

        HTTP/1.1 302 Found
        Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA
                  &state=xyz
      
  • 北京图灵学院博客服务器端向qq认证服务器申请令牌的HTTP请求,包含以下参数:

    • grant_type:表示使用的授权模式,必选项,此处的值固定为”authorization_code”。

    • code:表示上一步获得的授权码,必选项。

    • redirect_uri:表示重定向URI,必选项,且必须与上一步中的该参数值保持一致。

    • client_id:表示客户端ID,必选项。

    • client_secret:服务器密码

    • 例如:

        POST /token HTTP/1.1
        Host: server.example.com
        Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
        Content-Type: application/x-www-form-urlencoded
      
        grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
        &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
      
  • qq认证服务器向北京图灵学院博客服务器发送的HTTP回复,包含以下参数:

    • access_token:表示访问令牌,必选项。

    • token_type:表示令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。

    • expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。

    • refresh_token:表示更新令牌,用来获取下一次的访问令牌,可选项。

    • scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。

    • 示例:

         HTTP/1.1 200 OK
         Content-Type: application/json;charset=UTF-8
         Cache-Control: no-store
         Pragma: no-cache
      
         {
           "access_token":"2YotnFZFEjr1zCsicMWpAA",
           "token_type":"example",
           "expires_in":3600,
           "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
           "example_parameter":"example_value"
         }
      

8.2. implicit

  • 此种方式不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了”授权码”这个步骤,因此得名

  • 所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证

  • 这种方式把令牌直接传给前端,是很不安全的

  • 只能用于一些安全要求不高的场景

  • 并且令牌的有效期必须非常短,通常就是会话期间(session)有效,浏览器关掉,令牌就失效了。

  • 访问的示例图如下所示

    ImplicitPattern

  • 上面第一步,北京图灵学院博客服务器提供一个链接,要求用户跳转到qq授权服务器,授权用户数据给

    • response_type参数为token,表示要求直接返回令牌。

    • 例如

        https://b.com/oauth/authorize?
          response_type=token&
          client_id=CLIENT_ID&
          redirect_uri=CALLBACK_URL&
          scope=read
      
  • 第二步,用户跳转到qq授权网站,登录后同意给予北京图灵学院博客网站授权。 这时,qq授权网站就会跳回redirect_uri参数指定的跳转网址,并且把令牌作为 URL 参数, 传给北京图灵学院博客网站。

    • token参数就是令牌,北京图灵学院博客网站因此直接在前端拿到令牌。

    • 令牌的位置是 URL 锚点(fragment),而不是查询字符串(querystring), 这是因为 OAuth 2.0 允许跳转网址是 HTTP 协议,因此存在”中间人攻击”的风险, 而浏览器跳转时,锚点不会发到服务器,就减少了泄漏令牌的风险。

    • 例如:

      https://a.com/callback#token=ACCESS_TOKEN
      

8.3. 密码方式

  • 用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌

  • 这种方式需要用户给出自己的用户名/密码,风险很大

  • 只适用于其他授权方式都无法采用的情况,而且必须是用户高度信任的应用。

  • 示例如图: PasswordPattern

  • 第一步,北京图灵学院博客网站要求用户提供qq授权网站的用户名和密码。

    • 拿到以后,北京图灵学院博客就直接向qq授权服务器请求令牌。

    • grant_type参数是授权方式,这里的password表示”密码式”

    • username和password是qq网的用户名和密码。

    • 例如:

        https://oauth.b.com/token?
          grant_type=password&
          username=USERNAME&
          password=PASSWORD&
          client_id=CLIENT_ID
      
  • 第二步

    • qq授权网站验证身份通过后,直接给出令牌
    • 这时不需要跳转,而是把令牌放在 JSON 数据里面,作为 HTTP 回应,北京图灵学院博客因此拿到令牌。

8.4. 凭证模式

  • 适用于没有前端的命令行应用,即在命令行下请求令牌。

  • 这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即有可能多个用户共享同一个令牌。

  • 第一步

    • A 应用在命令行向 B 发出请求。

    • grant_type参数等于client_credentials表示采用凭证式

    • client_id和client_secret用来让qq认证服务器确认申请者的身份。

    • 例如:

        https://oauth.b.com/token?
          grant_type=client_credentials&
          client_id=CLIENT_ID&
          client_secret=CLIENT_SECRET
      
  • 第二步,B 网站验证通过以后,直接返回令牌。

  • 令牌的使用

    • 北京图灵学院博客网站拿到令牌以后,就可以向qq网站的 API 请求数据了

    • 每个发到 API 的请求,都必须带有令牌。

    • 具体做法是在请求的头信息,加上一个Authorization字段,令牌就放在这个字段里面。

    • 例如:

        curl -H "Authorization: Bearer ACCESS_TOKEN" \
        "https://api.b.com"
      
  • 更新令牌

    • OAuth 2.0 允许用户自动更新令牌。

    • 授权网站颁发令牌的时候,一次性颁发两个令牌

      • 获取数据令牌
      • 获取新的令牌(refresh token 字段)。
    • 令牌到期前,用户使用 refresh token 发一个请求,去更新令牌。

    • 例如:

        https://b.com/oauth/token?
          grant_type=refresh_token&
          client_id=CLIENT_ID&
          client_secret=CLIENT_SECRET&
          refresh_token=REFRESH_TOKEN